using System;
using System.Collections;
using System.Collections.Generic;
using Main.Event;
using Main.Save;
using Main.UI;
using UnityEngine;
using UnityEngine.SceneManagement;
using ZSW.Framework;

namespace Main.Transition
{
    public class SceneTransitionManager : ZSWF_Singleton<SceneTransitionManager>, ISaveable
    {
        [SceneName]
        public string startSceneName = string.Empty;


        public static string CurrentScene => SceneManager.GetActiveScene().name;

        public string GUID => GetComponent<DataGUID>().guid;

        private UI_Fade fade;

        public override void Init()
        {
            base.Init();
            fade = FindObjectOfType<UI_Fade>(true);
            MainEventSystem.TransitionEvent += TransitionScene;
            MainEventSystem.StartNewGameEvent += OnStartNetGame;


            ISaveable saveable = this;
            saveable.RegisterSaveable();
        }

        private void OnStartNetGame(int obj)
        {
            StartCoroutine(LoadSaveDataScene(startSceneName));
        }

        public void LoadFirstScene()
        {
            StartCoroutine(LoadSceneSetActive(startSceneName));
        }

        private void TransitionScene(string newSceneName, Vector3 targetPosition)
        {
            StartCoroutine(transitionScene(newSceneName, targetPosition));
        }

        private IEnumerator transitionScene(string newSceneName, Vector3 targetPosition)
        {
            MainEventSystem.CallBeforeLoadSceneEvent();

            fade.SwitchState(true);

            yield return new WaitForSeconds(Settings.SCENE_TRANSITION_DURATION);

            yield return SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene());

            yield return LoadSceneSetActive(newSceneName);

            fade.SwitchState(false);

            MainEventSystem.CallMoveToPosition(targetPosition);

            yield return new WaitForSeconds(Settings.SCENE_TRANSITION_DURATION);
        }

        private IEnumerator LoadSceneSetActive(string sceneName)
        {
            yield return SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);

            Scene newScene = SceneManager.GetSceneAt(SceneManager.sceneCount - 1);

            SceneManager.SetActiveScene(newScene);

            MainEventSystem.CallAfterLoadSceneEvent();
        }

        private IEnumerator LoadSaveDataScene(string sceneName)
        {
            fade.SwitchState(true);
            yield return new WaitForSeconds(Settings.SCENE_TRANSITION_DURATION);

            if (CurrentScene != "Main")
            {
                MainEventSystem.CallBeforeLoadSceneEvent();
                yield return SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene());
            }

            yield return LoadSceneSetActive(sceneName);

            fade.SwitchState(false);

            yield return new WaitForSeconds(Settings.SCENE_TRANSITION_DURATION);
        }

        public GameSaveData GenerateSaveData()
        {
            var data = new GameSaveData();
            data.DataSceneName = CurrentScene;

            return data;
        }

        public void RestoreData(GameSaveData data)
        {
            StartCoroutine(LoadSaveDataScene(data.DataSceneName));
        }
    }
}

